/*
 * RtspRelay.cpp
 *
 *  Created on: 2016年4月29日
 *      Author: terry
 */

#include "BasicType.h"
#include "RtspRelay.h"

#include "CLog.h"
#include "TSafeStr.h"

#include "RelayChanneltable.h"
#include "CRelayChannel.h"


static av::RelayChanneltable& getChannelTable()
{
	return av::RelayChanneltable::instance();
}

/*
static void copy(av::MediaFormat& mfmt, const MFormat* fmt)
{
    mfmt.m_codec = fmt->codec;
    mfmt.m_width= fmt->width;
    mfmt.m_height = fmt->height;
    mfmt.m_framerate = fmt->fps;
    mfmt.m_profile = fmt->profile;
    mfmt.m_clockRate = fmt->clockRate;

    mfmt.m_audioCodec = fmt->audioCodec;
    mfmt.m_channels = fmt->channels;
    mfmt.m_sampleRate = fmt->sampleRate;
    mfmt.m_audioProfile = fmt->audioProfile;
    mfmt.m_audioRate = fmt->audioRate;

    if (fmt->vProp && fmt->vPropSize > 0)
    {
        mfmt.m_videoProp.assign((char*)fmt->vProp, fmt->vPropSize);
    }
}


static void copyTo(const av::MediaFormat& mfmt, MFormat* fmt)
{
    fmt->codec = mfmt.m_codec;
    fmt->width = mfmt.m_width;
    fmt->height = mfmt.m_height;
    fmt->fps = mfmt.m_framerate;
    fmt->profile = mfmt.m_profile;
    fmt->clockRate = mfmt.m_clockRate;

    fmt->audioCodec = mfmt.m_audioCodec;
    fmt->channels = mfmt.m_channels;
    fmt->sampleRate = mfmt.m_sampleRate;
    fmt->audioProfile = mfmt.m_audioProfile;
    fmt->audioRate = mfmt.m_audioRate;

    fmt->vProp = (uint8_t*)mfmt.m_videoProp.c_str();
    fmt->vPropSize = mfmt.m_videoProp.size();

}
*/


/**
 * 初始化
 * @param port	RTSP端口
 * @return 0 表示成功
 */
DLLEXPORT int relay_init(int port)
{
	int rc = caster_init(port);
	rtpcaster_init();

	CLog::setLogger(CLog::COUT);
	CLog::info("relay_init(%d)\n", port);

	return rc;
}

/**
 * 反初始化
 * @return
 */
DLLEXPORT int relay_quit()
{
	av::RelayChanneltable& chlTable = getChannelTable();
	chlTable.clear();
	
	caster_quit();
	rtpcaster_quit();

	return 0;
}

/**
 * 设置端口范围
 * @param minPort
 * @param maxPort
 * @return
 */
DLLEXPORT int relay_set_port_range(int minPort, int maxPort)
{
	caster_set_port_range(minPort, maxPort);
	rtpcaster_set_port_range(minPort, maxPort);

	return 0;
}

/**
 * 打开通道
 * @param handle 返回的通道句柄
 * @param name	通道名称
 * @param fmt   媒体格式
 * @return 0 表示成功
 */
DLLEXPORT int relay_chl_open(HANDLE* handle, int protocol, const char* name, const MFormat* fmt)
{
	if (!name || strlen(name) <= 0)
	{
		return EINVAL;
	}

    if (!fmt)
    {
        return EINVAL;
    }

	av::RelayChanneltable& chlTable = getChannelTable();
	if (chlTable.exists(name))
	{
		return EEXIST;
	}

	av::RelayChannelPtr chl(new av::CRelayChannel());
	int rc = chl->open(protocol, name, *fmt);
    if (rc == 0)
    {
	    chlTable.put(chl.get(), chl);

	    *handle = chl.get();
    }

	return 0;
}

/**
 * 关闭通道
 * @param handle 通道句柄
 */
DLLEXPORT void relay_chl_close(HANDLE handle)
{
	av::RelayChanneltable& chlTable = getChannelTable();
	av::RelayChannelPtr chl;
	chlTable.find(handle, chl);
	if (!chl)
	{
		return ;
	}

	chl->close();

	chlTable.remove(handle);

	return ;
}

/**
 * 通道是否打开, 即判断有效
 * @param handle 通道句柄
 * @return > 0 表示有效
 */
DLLEXPORT int relay_chl_is_open(HANDLE handle)
{
	av::RelayChanneltable& chlTable = getChannelTable();
	return chlTable.exist(handle);
}

/**
 * 获取通道媒体格式
 * @param handle   通道句柄
 * @param fmt 媒体格式
 * @return 0 表示成功
 */
DLLEXPORT int relay_chl_get_format(HANDLE handle, MFormat* fmt)
{
	if (!fmt)
	{
		return EINVAL;
	}

	av::RelayChanneltable& chlTable = getChannelTable();
	av::RelayChannelPtr chl;
	chlTable.find(handle, chl);
	if (!chl)
	{
		return ENOENT;
	}

	chl->getFormat(fmt);

	return 0;
}


DLLEXPORT int relay_chl_get_transport(HANDLE handle, char* videoUrl, int videoSize, char* audioUrl, int audioSize)
{
	av::RelayChanneltable& chlTable = getChannelTable();
	av::RelayChannelPtr chl;
	chlTable.find(handle, chl);
	if (!chl)
	{
		return ENOENT;
	}

	std::string audioStr;
	std::string str = chl->getTransport(audioStr);

	if (videoUrl)
	{
		comn::copyStr(videoUrl, videoSize, str);
	}

	if (audioUrl)
	{
		comn::copyStr(audioUrl, audioSize, audioStr);
	}

	return 0;
}


/**
 * 设置媒体源
 * @param handle
 * @param url	媒体源URL
 * @return 0 表示成功
 */
DLLEXPORT int relay_chl_set_source(HANDLE handle, const char* videoUrl, const char* audioUrl)
{
	av::RelayChanneltable& chlTable = getChannelTable();
	av::RelayChannelPtr chl;
	chlTable.find(handle, chl);
	if (!chl)
	{
		return ENOENT;
	}

	int rc = chl->setSource(videoUrl, audioUrl);

	return rc;
}

/**
 * 设置事件回调句柄
 * @param cb		回调函数指针
 * @param context	回调环境
 * @return
 */
DLLEXPORT void relay_set_event_callback(RtspCasterEventCallback cb, void* context)
{
	caster_set_event_callback(cb, context);
}

DLLEXPORT HANDLE relay_chl_find(const char* name)
{
	if ((name == NULL) || (strlen(name) <= 0))
	{
		return NULL;
	}

	av::RelayChanneltable& chlTable = getChannelTable();
	av::RelayChannelPtr chl = chlTable.findWithName(name);
	return chl.get();
}
